package com.docchatlink.iflytek.client;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.docchatlink.dto.UploadResp;
import com.docchatlink.dto.chat.ChatMessage;
import com.docchatlink.dto.chat.ChatRequest;
import com.docchatlink.iflytek.config.IflytekConfig;
import com.docchatlink.util.ApiAuthUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 连接星火知识库V1.0
 * </p>
 *
 * @author Mr.piggy
 * @since 2024/3/27
 */
@Service
@Slf4j
public class IflytekDocClient {

    @Resource
    private IflytekConfig iflytekConfig;

    /**
     * 文档上传
     */
    public UploadResp fileUpload(MultipartFile file) throws IOException {
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .connectTimeout(20, TimeUnit.SECONDS)
                .build();

//        //String转RequestBody String、ByteArray、ByteString都可以用toRequestBody()
//        MediaType mediaType=MediaType.Companion.parse("application/json;charset=utf-8");
//        RequestBody stringBody=RequestBody.Companion.create("body参数", mediaType);
//        Request request=new Request
//                .Builder()
//                .post(stringBody)
//                .build();
//
//        //File转RequestBody
//        MediaType mediaType=MediaType.Companion.parse("text/x-markdown; charset=utf-8");
//        File file=new File("");
//        RequestBody fileBody=RequestBody.Companion.create(file,mediaType);
//        Request request=new MultipartBody.Builder()
//                .addFormDataPart("file", file.getName(),fileBody)
//                .build();


        RequestBody fileBody = RequestBody.Companion.create(file.getBytes(),MediaType.parse("multipart/form-data"));

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        builder.addFormDataPart("file", file.getOriginalFilename(), fileBody);
        builder.addFormDataPart("fileType", "wiki");
        RequestBody body = builder.build();
        long ts = System.currentTimeMillis() / 1000;
        String signature = ApiAuthUtil.getSignature(iflytekConfig.getAppId(), iflytekConfig.getApiSecret(), ts);
        Request request = new Request.Builder()
                .url(iflytekConfig.getFileUploadUrl())
                .post(body)
                .addHeader("appId", iflytekConfig.getAppId())
                .addHeader("timestamp", String.valueOf(ts))
                .addHeader("signature", signature)
                .build();
        try {
            log.info("{},{},{},{}", file.getOriginalFilename(), iflytekConfig.getFileUploadUrl(), iflytekConfig.getAppId(), iflytekConfig.getApiSecret());
            Response response = okHttpClient.newCall(request).execute();
            if (Objects.equals(response.code(), 200)) {
                String respBody = response.body().string();
                return JSONUtil.toBean(respBody, UploadResp.class);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }


    public String chatAn(String fileId, String question) {
        StringBuffer buffer = new StringBuffer();

        ChatMessage message = new ChatMessage();
        message.setRole("user");
        message.setContent(question);
        // 请求内容
        ChatRequest request = ChatRequest.builder()
                .fileIds(Collections.singletonList(fileId))
                .topN(3)
                .messages(Collections.singletonList(message))
                .build();

        try {
            long start = System.currentTimeMillis();
            // wsCloseFlag: websocket 关闭状态 true: 关闭 false: 打开
            final boolean[] wsCloseFlag = {false};
            // 构造url鉴权
            long ts = System.currentTimeMillis() / 1000;
            String signature = ApiAuthUtil.getSignature(iflytekConfig.getAppId(), iflytekConfig.getApiSecret(), ts);
            String requestUrl = iflytekConfig.getChatUrl() + "?" + "appId=" + iflytekConfig.getAppId() + "&timestamp=" + ts + "&signature=" + signature;
            log.info("chatAn  requestUrl :{}", requestUrl);
            // ws
            Request wsRequest = (new Request.Builder()).url(requestUrl).build();
            OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
            WebSocket webSocket = okHttpClient.newWebSocket(wsRequest, new WebSocketListener() {
                @Override
                public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                    super.onClosed(webSocket, code, reason);
                    webSocket.close(1002, "websocket finish");
                    okHttpClient.connectionPool().evictAll();
                }

                @Override
                public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
                    super.onFailure(webSocket, t, response);
                    webSocket.close(1001, "websocket finish");
                    okHttpClient.connectionPool().evictAll();
                }

                @Override
                public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
                    System.out.println(text);
                    JSONObject jsonObject = JSONUtil.parseObj(text);
                    String content = jsonObject.getStr("content");
                    if (StrUtil.isNotEmpty(content)) {
                        buffer.append(content);
                    }
                    if (Objects.equals(jsonObject.getInt("status"), 2)) {
                        System.out.println("回答内容：" + buffer);
                        webSocket.close(1000, "websocket finish");
                        okHttpClient.connectionPool().evictAll();
//                    System.exit(0);
                        wsCloseFlag[0] = true;
                    }
                }
            });

//            while (!webSocketClient.getReadyState().equals(org.java_websocket.WebSocket.READYSTATE.OPEN)) {
//                log.info("【WebSocket】正在连接...");
//                Thread.sleep(2000);
//            }
            log.info("【WebSocket】连接成功");

            log.info("请求参数: {}", JSONUtil.toJsonStr(request));
            webSocket.send(JSONUtil.toJsonStr(request));

            while (!wsCloseFlag[0]) {
                log.info("【WebSocket】等待服务端返回完毕后关闭...");
                Thread.sleep(2000);
            }
            log.info("websocket 耗时: {}ms", System.currentTimeMillis() - start);
        } catch (Exception e) {
            log.info("出现异常", e);
        }
        return buffer.toString();
    }

    /**
     * 文档问答
     */
    public void chat(String fileId, String question) {
        ChatMessage message = new ChatMessage();
        message.setRole("user");
        message.setContent(question);
        // 请求内容
        ChatRequest request = ChatRequest.builder()
                .fileIds(Collections.singletonList(fileId))
                .topN(3)
                .messages(Collections.singletonList(message))
                .build();

        // 构造url鉴权
        long ts = System.currentTimeMillis() / 1000;
        String signature = ApiAuthUtil.getSignature(iflytekConfig.getAppId(), iflytekConfig.getApiSecret(), ts);
        String requestUrl = iflytekConfig.getChatUrl() + "?" + "appId=" + iflytekConfig.getAppId() + "&timestamp=" + ts + "&signature=" + signature;
        log.info("chat  requestUrl :{}", requestUrl);
        // ws
        Request wsRequest = (new Request.Builder()).url(requestUrl).build();
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
        StringBuffer buffer = new StringBuffer();
        WebSocket webSocket = okHttpClient.newWebSocket(wsRequest, new WebSocketListener() {
            @Override
            public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
                super.onClosed(webSocket, code, reason);
                webSocket.close(1002, "websocket finish");
                okHttpClient.connectionPool().evictAll();
            }

            @Override
            public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
                super.onFailure(webSocket, t, response);
                webSocket.close(1001, "websocket finish");
                okHttpClient.connectionPool().evictAll();
            }

            @Override
            public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
                System.out.println(text);
                JSONObject jsonObject = JSONUtil.parseObj(text);
                String content = jsonObject.getStr("content");
                if (StrUtil.isNotEmpty(content)) {
                    buffer.append(content);
                }
                if (Objects.equals(jsonObject.getInt("status"), 2)) {
                    System.out.println("回答内容：" + buffer);
                    webSocket.close(1000, "websocket finish");
                    okHttpClient.connectionPool().evictAll();
//                    System.exit(0);
                }
            }
        });
        log.info("请求参数: {}", JSONUtil.toJsonStr(request));
        webSocket.send(JSONUtil.toJsonStr(request));
    }

    /**
     * 发起文档总结
     */
    public UploadResp startSummary(String fileId) {
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .connectTimeout(20, TimeUnit.SECONDS)
                .build();

        long ts = System.currentTimeMillis() / 1000;
        // 创建一个FormBody.Builder对象
        FormBody.Builder formBuilder = new FormBody.Builder();

        // 添加POST参数
        formBuilder.add("fileId", fileId);

        // 创建一个RequestBody对象，用于包装表单数据
        RequestBody requestBody = formBuilder.build();

        // 创建请求
        Request request = new Request.Builder()
                .url(iflytekConfig.getStartSummaryUrl())
                .post(requestBody)
                .addHeader("appId", iflytekConfig.getAppId())
                .addHeader("timestamp", String.valueOf(ts))
                .addHeader("signature", ApiAuthUtil.getSignature(iflytekConfig.getAppId(), iflytekConfig.getApiSecret(), ts))
                .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (Objects.equals(response.code(), 200)) {
                String respBody = response.body().string();
                return JSONUtil.toBean(respBody, UploadResp.class);
            }
        } catch (IOException e) {
            log.error("调用异常", e);
            throw new RuntimeException("调用异常", e);
        }
        return null;
    }

    /**
     * 获取文档总结/概要内容
     */
    public UploadResp fileSummary(String fileId) {
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .connectTimeout(20, TimeUnit.SECONDS)
                .build();

        long ts = System.currentTimeMillis() / 1000;
        // 创建一个FormBody.Builder对象
        FormBody.Builder formBuilder = new FormBody.Builder();

        // 添加POST参数
        formBuilder.add("fileId", fileId);

        // 创建一个RequestBody对象，用于包装表单数据
        RequestBody requestBody = formBuilder.build();

        // 创建请求
        Request request = new Request.Builder()
                .url(iflytekConfig.getFileSummaryUrl())
                .post(requestBody)
                .addHeader("appId", iflytekConfig.getAppId())
                .addHeader("timestamp", String.valueOf(ts))
                .addHeader("signature", ApiAuthUtil.getSignature(iflytekConfig.getAppId(), iflytekConfig.getApiSecret(), ts))
                .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (Objects.equals(response.code(), 200)) {
                String respBody = response.body().string();
                return JSONUtil.toBean(respBody, UploadResp.class);
            }
        } catch (IOException e) {
            log.error("调用异常", e);
            throw new RuntimeException("调用异常", e);
        }
        return null;
    }

    public String initChat() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

}
